package com.zyy.game.tianlong.network;

import com.zyy.game.tianlong.network.callback.ActiveCallBack;
import com.zyy.game.tianlong.network.callback.EventExceptionCallBack;
import com.zyy.game.tianlong.network.callback.InActiveCallBack;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 事件分发处理器
 *
 * @author relufi
 * @date 2019/7/22 0022 10:07
 */
@Component
@ChannelHandler.Sharable
@Slf4j
public class GameDispatcher extends ChannelInboundHandlerAdapter {
    private final GameHandlersAware gameHandlersAware;
    private final ActiveCallBack activeCallBack;
    private final InActiveCallBack inActiveCallBack;
    private final EventExceptionCallBack eventExceptionCallBack;

    public GameDispatcher(GameHandlersAware gameHandlersAware, ActiveCallBack activeCallBack, InActiveCallBack inActiveCallBack, EventExceptionCallBack eventExceptionCallBack) {
        this.gameHandlersAware = gameHandlersAware;
        this.activeCallBack = activeCallBack;
        this.inActiveCallBack = inActiveCallBack;
        this.eventExceptionCallBack = eventExceptionCallBack;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        eventExceptionCallBack.exceptionCaught(new GameContext(ctx), cause);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object objMsg) {
        SocketMsg msg = ((SocketMsg) objMsg);
        GameContext gameContext = new GameContext(ctx);
        try {
            gameHandlersAware.getHandlerMethod(msg.getOpCode(), msg.getSubCode()).invoke(gameContext, msg);
        } catch (Exception cause) {
            eventExceptionCallBack.exceptionCaught(gameContext, cause);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        inActiveCallBack.channelInactive(new GameContext(ctx));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        activeCallBack.channelActive(new GameContext(ctx));
    }
}
